package com.xht.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xht.constants.SystemConstants;
import com.xht.domain.ResponseResult;
import com.xht.domain.dto.UserChangeStatusDto;
import com.xht.domain.dto.UserDto;
import com.xht.domain.entity.LoginUser;
import com.xht.domain.entity.Role;
import com.xht.domain.entity.User;
import com.xht.domain.entity.UserRole;
import com.xht.enums.AppHttpCodeEnum;
import com.xht.exception.SystemExceptin;
import com.xht.mapper.RoleMapper;
import com.xht.mapper.UserMapper;
import com.xht.service.UserRoleService;
import com.xht.service.UserService;
import com.xht.utils.BeanCopyUtils;
import com.xht.utils.SecurityUtils;
import com.xht.vo.PageVo;
import com.xht.vo.UserEditVo;
import com.xht.vo.UserInfo;
import com.xht.vo.UserListVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 用户表(User)表服务实现类
 *
 * @author makejava
 * @since 2025-02-28 13:50:36
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 密码加密 的 bean
     */
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RoleMapper roleMapper;

    @Override
    public ResponseResult userInfo() {
        //获取当前用户id
        Long userId =
                //其实底层是 调用了 SecurityContextHolder.getContext().getAuthentication().getPrincipal() , 可以 利用强制转换为定义的类
                SecurityUtils.getUserId();

        //根据用户id查询用户信息
        User user = getById(userId);
        //封装成UserInfo
        UserInfo userInfo = BeanCopyUtils.copyBean(user, UserInfo.class);

        return ResponseResult.okResult(userInfo);
    }

    /**
     * 保存个人信息
     *
     * @param user
     * @return
     */
    @Override
    public ResponseResult updateUserInfo(User user) {
        //更新用户信息
        //TODO 更新前加入判断条件  传过来的id 与 token id要一直才能 修改
        Long id = user.getId();
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long headerId = loginUser.getUser().getId();
        if (Objects.equals(id, headerId)) {
            updateById(user);
            return ResponseResult.okResult();
        } else {
            //可能是非法操作
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        //TODO 更新redis
        //由于拦截器那边不太熟悉

    }

    /**
     * 用户注册
     *
     * @param user
     * @return
     */
    @Override
    public ResponseResult register(User user) {

        // TODO 可以使用Validation 改进代码
        //判断用户名是否为空
        if (!StringUtils.hasText(user.getUserName())) {
            throw new SystemExceptin(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        //判断昵称是否为空
        if (!StringUtils.hasText(user.getNickName())) {
            throw new SystemExceptin(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        //判断密码是否为空
        if (!StringUtils.hasText(user.getPassword())) {
            throw new SystemExceptin(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        //判断邮箱是否为空
        if (!StringUtils.hasText(user.getEmail())) {
            throw new SystemExceptin(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        //判断用户名 是否在数据库存在
        if (exitUseName(user.getUserName())) {
            throw new SystemExceptin(AppHttpCodeEnum.USERNAME_EXIST);
        }
        //进行密码加密
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);

        //数据库添加用户信息即可
        save(user);

        return null;
    }

    /**
     * 后台模块-用户管理-- 展示用户列表 可以模糊查询和分页
     *
     * @param pageNum
     * @param pageSize
     * @param userName
     * @param phonenumber
     * @param status
     * @return
     */
    @Override
    public ResponseResult GetList(Integer pageNum, Integer pageSize, String userName, String phonenumber, String status) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(userName), User::getUserName, userName);
        queryWrapper.eq(StringUtils.hasText(phonenumber), User::getPhonenumber, phonenumber);
        queryWrapper.eq(StringUtils.hasText(status), User::getStatus, status);
        Page<User> page = new Page<>(pageNum, pageSize);
        page(page, queryWrapper);

        //封转数据
        List<User> userList = page.getRecords();
        List<UserListVo> userListVos = BeanCopyUtils.copyBeanList(userList, UserListVo.class);
        PageVo pageVo = new PageVo(userListVos, page.getTotal());

        return ResponseResult.okResult(pageVo);
    }

    /**
     * 增加用户 1/user表 2/role表
     *
     * @param userDto
     * @return
     */
    @Override
    @Transactional
    public ResponseResult addUser(UserDto userDto) {
        //非空 和 存在 判断
        String userName = userDto.getUserName();
        if (!StringUtils.hasText(userName)) {
            throw new SystemExceptin(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (exitUseName(userName)) {
            throw new SystemExceptin(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if (exitPhone(userDto.getPhonenumber())) {
            throw new SystemExceptin(AppHttpCodeEnum.PHONENUMBER_EXIST);
        }
        if (exitEmail(userDto.getEmail())) {
            throw new SystemExceptin(AppHttpCodeEnum.EMAIL_EXIST);
        }

        User user = BeanCopyUtils.copyBean(userDto, User.class);
        //加密
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        //保持数据到user表
        save(user);
        Long id = user.getId();
        //保存数据到user_role表
        List<UserRole> collect = userDto.getRoleIds().stream()
                .map(new Function<String, UserRole>() {
                    @Override
                    public UserRole apply(String roleId) {
                        return new UserRole(id, Long.valueOf(roleId));
                    }
                }).collect(Collectors.toList());
        userRoleService.saveBatch(collect);

        return ResponseResult.okResult();
    }

    /**
     * 逻辑删除 用户
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult deleteUser(Integer id) {
        //不能删除当前用户(不能删除自己)
        //获取当前用户id
        Long NowId = SecurityUtils.getUserId();
        long value = id.longValue();//先转换为Long再比较
        if (NowId.equals(value)) { //不能删除当前操作的用户
            throw new SystemExceptin(AppHttpCodeEnum.NOT_DELETE_YOURSELVES);
        }

        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class).eq(User::getId, id)
                .set(User::getDelFlag, SystemConstants.USER_STATUS_DELETE);
        update(updateWrapper);

        return ResponseResult.okResult();
    }

    /**
     * 后台--更新用户信息--回显信息
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult getUserInfoById(Integer id) {
        //查询user
        LambdaQueryWrapper<User> queryWrapper1 = Wrappers.lambdaQuery(User.class).eq(User::getId, id);
        User user = getOne(queryWrapper1);
        //查询对应的user_role roleIds
        LambdaQueryWrapper<UserRole> queryWrapper2 = Wrappers.lambdaQuery(UserRole.class).eq(UserRole::getUserId, id);
        List<String> roleIds = userRoleService.list(queryWrapper2).stream()
                .map(new Function<UserRole, String>() {
                    @Override
                    public String apply(UserRole userRole) {
                        return userRole.getRoleId().toString();
                    }
                }).collect(Collectors.toList());
        //查询所有roles
        LambdaQueryWrapper<Role> queryWrapper3 = Wrappers.lambdaQuery(Role.class).eq(Role::getStatus, SystemConstants.ROLE_STATUS_NORMAL);
        List<Role> roles = roleMapper.selectList(queryWrapper3);

        //封装数据
        UserEditVo userEditVo = new UserEditVo(roleIds, roles, user);

        return ResponseResult.okResult(userEditVo);
    }

    /**
     * 后台模块--更新 编辑好的 用户信息
     *
     * @param userDto
     * @return
     */
    @Override
    @Transactional
    public ResponseResult updateUser(UserDto userDto) {
        Long id = userDto.getId();
        //更新 user表
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class).eq(User::getId, id);
        User user = BeanCopyUtils.copyBean(userDto, User.class);
        update(user, updateWrapper);

        //更新user_role表
        LambdaQueryWrapper<UserRole> queryWrapper = Wrappers.lambdaQuery(UserRole.class)
                .eq(UserRole::getUserId, id);
        userRoleService.remove(queryWrapper);//先删除
        List<UserRole> userRoles = userDto.getRoleIds().stream()  //再重新插入
                .map(new Function<String, UserRole>() {
                    @Override
                    public UserRole apply(String roleId) {
                        return new UserRole(id, Long.valueOf(roleId));
                    }
                }).collect(Collectors.toList());
        userRoleService.saveBatch(userRoles);

        return ResponseResult.okResult();
    }

    /**
     * 修改 用户状态
     *
     * @param userChangeStatusDto
     * @return
     */
    @Override
    public ResponseResult changeStatus(UserChangeStatusDto userChangeStatusDto) {
        Long id = userChangeStatusDto.getUserId();
        String status = userChangeStatusDto.getStatus();
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class).eq(User::getId, id)
                .set(User::getStatus, status);
        update(updateWrapper);
        return ResponseResult.okResult();
    }

    //判断数据库中 是否存在 当前相同的用户名
    private boolean exitUseName(String userName) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserName, userName);

        User one = getOne(wrapper);
        return !Objects.isNull(one);
    }

    private boolean exitPhone(String phone) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhonenumber, phone);

        User one = getOne(wrapper);
        return !Objects.isNull(one);
    }

    private boolean exitEmail(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);

        User one = getOne(wrapper);
        return !Objects.isNull(one);
    }


}

